package com.echo.boot.structure.linearlist.linked.circle;

import com.echo.boot.structure.linearlist.list.MyAbstractList;

/**
 * Created with IntelliJ IDEA
 * Created By CQ
 * Date: 2020/4/29
 * Time: 21:48
 * 循环单向链表,最后一元素next 指向 第一个元素,first 指向第一个元素，所以 end.next = first
 * 哈希表用的是单向链表
 * 边界是否符合条件 index = 0; index = size - 1; index = size;
 *
 * @author Administrator
 */
public class MySingleCircleLinkedList<E> extends MyAbstractList<E> {

    private Node<E> first;
    private Node<E> current;

    private static class Node<E> {
        // 每个节点储存里两个元素
        // 一个是信息，一个是下一个节点的地址
        E element;
        Node<E> next;

        public Node(E element, Node<E> node) {
            this.element = element;
            this.next = node;
        }
    }

    @Override
    public void clear() {
        size = 0;
        // 把第一个引用地址去掉,后面的就全部失效
        first.next = null;
    }

    @Override
    public E get(int index) {
        return node(index).element;
    }

    @Override
    public E set(int index, E element) {
        Node<E> node = node(index);
        E old = node.element;
        node.element = element;
        return old;
    }

    @Override
    public void add(int index, E element) {
        rangeCheckForAdd(index);
        if (index == 0) {
            // 循环单向链表,最后一元素next 指向 第一个元素,first 指向第一个元素，所以 end.next = first
            // first 指向的是下一个的节点
            Node<E> newFirst = new Node<>(element, first);
            // 添加在 头部
            // 拿到最后一个元素node(size); 在这里(size-1);原因是first指向了新的元素,再遍历情况下拿到的是上一个元素
            Node<E> end = (size == 0) ? newFirst : node(size - 1);
            end.next = newFirst;
            first = newFirst;

            /**
             // 出现的情况：1 ： NullPointerException，我的写法：
             // 先拿到节点
             Node<E> end = (size == 0) ? first : node(size - 1);
             first = new Node<E>(element,first);
             //这个时候end 是 null;
             end.next = first;
             */


        } else {
            Node<E> prev = node(index - 1);
            prev.next = new Node<E>(element, prev.next);
        }
        size++;
    }

    @Override
    public E remove(int index) {
        rangeCheck(index);
        Node<E> node = first;
        if (index == 0) {
            if (size == 1) {
                // 元素只有一个的时候
                node = null;
            } else {
                // size > 1
                // 首先拿到初始的最后一个节点,
                Node<E> end = node(size - 1);
                first = first.next;
                end.next = first;
            }
        } else {
            Node<E> prev = node(index - 1);
            node = prev.next;
            prev.next = node.next;
        }
        size--;
        return node.element;
    }

    private E remove(Node<E> node) {
        return node.element;
    }


    @Override
    public int indexOf(E element) {
        if (element == null) {
            Node<E> node = first;
            for (int i = 0; i < size; i++) {
                if (node.element == null) {
                    return i;
                }
                node = node.next;
            }
        } else {
            Node<E> node = first;
            for (int i = 0; i < size; i++) {
                if (element.equals(node.element)) {
                    return i;
                }
                node = node.next;
            }
        }
        return ELEMENT_NOT_FOUND;
    }


    private Node<E> node(int index) {
        rangeCheck(index);
        Node<E> node = first;
        for (int i = 0; i < index; i++) {
            node = node.next;
        }
        return node;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("size=").append(size);
        builder.append(", [");
        Node<E> node = first;
        for (int i = 0; i < size; i++) {
            if (i != 0) {
                builder.append(", ");
            }
            builder.append(node.element);
            node = node.next;
        }
        builder.append("]");
        return builder.toString();
    }

    public void reset() {
        current = first;
    }

    public E next() {
        if (current == null) {
            return null;
        }
        current = current.next;
        return current.element;
    }

    public E remove() {
        if (current == null) {
            return null;
        }
        remove(current);
        return null;
    }


}
